# Debugging

## 通过 VS Code 调试

1. 安装 `go install github.com/go-delve/delve/cmd/dlv@latest`
2. 安装 VS Code 扩展 [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) 和 [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)
3. 通过执行 `pnpm install && pnpm -w build:cli:dev` 构建 `@rspack/cli` 和 napi binding
4. 在 VS Code 的 `Run and Debug` 栏中, 选择 `Debug Rspack` 开始调试 `@rspack/cli` 的启动过程。 该任务可以在 `.vscode/launch.json` 中配置，会同时启动 Node 和 Rust 的调试器。

:::note
其他工具集成的一般是 Rspack 的 release 版本，其中并不包含调试信息，这时候需要使用对应的含有debug 的版本进行override替换，方可调试。
:::

### 常见调试场景指南

#### 调试 Rust

只需在指定的 Rust 代码处设置断点后启动 `Debug Rspack` 即可进行调试。

#### 调试 JavaScript

启动 `Debug Rspack` 时，选择 `--inspect` 或 `--inspect-brk` 选项，然后启动 `Attach JavaScript` 并选择相应进程的 PID 即可。

#### 调试已启动的 Rspack 进程

当 Rspack 被集成到其他框架或工具（如 Nx）中时，可能难以独立使用 Launch 模式启动 Rspack。此时，可以通过 attach 模式调试代码。启动 `Attach Rust` 并选择 Rspack 所属进程的 PID 即可,启动 `Attach JavaScript` 即可调试 JavaScript。

#### 调试发生死锁的 Rspack 进程

当使用 `Attach Rust` 将调试器 attach 到 Rspack 所属进程后，点击 Debugger 的 Pause 按钮即可在死锁现场设置断点。

## rust-lldb

`rust-lldb` 可用于从 debug 版本中获取 panic 信息

```bash
rust-lldb -- node /path/to/rspack build
```

启动后，按住 `r` 来执行程序。

例如，`examples/arco-pro` 运行崩溃了并且没有任何信息在[这个修复](https://github.com/web-infra-dev/rspack/pull/3195/files) 之前:

```
rspack/examples/arco-pro ❯ node ../../packages/rspack-cli/bin/rspack build
Rspack ██████████████████████░░░░░░░░░░░░░░░░░░ 56% building ./pages/welcome
zsh: bus error  node ../../packages/rspack-cli/bin/rspack build
```

使用 `rust-lldb`

```bash
rspack/examples/arco-pro ❯ rust-lldb -- node ../../packages/rspack-cli/bin/rspack build
```

按下 `r` 然后会打印:

```
Process 23110 stopped
* thread #10, name = 'tokio-runtime-worker', stop reason = EXC_BAD_ACCESS (code=2, address=0x70000cc66560)
    frame #0: 0x0000000140d0db4b rspack.darwin-x64.node`swc_ecma_parser::parser::expr::ops::_$LT$impl$u20$swc_ecma_parser..parser..Parser$LT$I$GT$$GT$::parse_unary_expr::h29f49330a806839c(self=0x0000000000000000) at ops.rs:244
   241 	    /// Parse unary expression and update expression.
   242 	    ///
   243 	    /// spec: 'UnaryExpression'
-> 244 	    pub(in crate::parser) fn parse_unary_expr(&mut self) -> PResult<Box<Expr>> {
   245 	        trace_cur!(self, parse_unary_expr);
   246 	        let start = cur_pos!(self);
   247
Target 0: (node) stopped.
```
